from util.error import ErrorCalculation

__author__ = 'Douglas'


class FeedforwardNetwork:
    def __init__(self):
        self.input_layer = None
        self.output_layer = None
        self.layers = []

    def add_layer(self, layer):
        if len(self.layers) == 0:
            self.input_layer = self.output_layer = layer
        else:
            self.output_layer.next = layer
            self.output_layer = layer

        self.layers.append(layer)

    def calculate_error(self, training_set):
        error = ErrorCalculation()

        for row in training_set:
            self.compute_outputs(row.input_pattern)
            error.update_error(self.output_layer.fire, row.ideal_output)

        return error.calculate_rms()

    def compute_outputs(self, input_pattern):
        if len(input_pattern) == self.input_layer.neuron_count:
            for layer in self.layers:
                if layer.is_input:
                    layer.compute_outputs(input_pattern)
                elif layer.is_hidden:
                    layer.compute_outputs()

            return self.output_layer.fire

        else:
            raise Exception("The input must have the same length as input layer length")

    def reset(self):
        for layer in self.layers:
            layer.reset()